//8．巨人航空公司的机群由12个座位的飞机组成。
//它每天飞行一个航班。根据下面的要求，编写一个座位预订程序。　　
//a．该程序使用一个内含12个结构的数组。
//每个结构中包括：一个成员表示座位编号、一个成员表示座位是否已被预订、
//一个成员表示预订人的名、一个成员表示预订人的姓。　　
//b．该程序显示下面的菜单：
//To choose a function, enter its letter label:
//a) Show number of empty seats
//b) Show list of empty seats
//c) Show alphabetical list of seats
//d) Assign a customer to a seat assignment
//e) Delete a seat assignment
//f) Quit 　
//c．该程序能成功执行上面给出的菜单。选择d)和e)要提示用户进行额外输入，每个选项都能让用户中止输入。　　
//d．执行特定程序后，该程序再次显示菜单，除非用户选择f)。

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#define LEN 14
#define SEATS 12
#define EMPTY 0
#define TAKEN 1
struct planestate {
    int seat_id;
    int status;
    char last[LEN];
    char first[LEN];
};

static void eatline();

static int get_i();

static int get_opt_seat(int min, int max);

char *s_gets(char *st, int n);

//选择菜单
static char choice_menu();

//Show number of empty seats
static void show_empty_seats_number(struct planestate plane[], int size);

//Show list of empty seats
static void show_empty_seats(struct planestate plane[], int size);

//Show alphabetical list of seats（根据姓名排序）
static void show_alphabetical_seats(struct planestate plane[], int size);

//Assign a customer to a seat assignment
static void assignment(struct planestate *plan);


int main() {
    const char filepath[] = "../unit14/planestats.dat";
    FILE *fp;
    char choice;
    int seat_id;
    size_t planestate_size = sizeof(struct planestate);
    size_t size = (size_t) SEATS;
    struct planestate plane[SEATS];

    //读取文件中的数据
    if ((fp = fopen(filepath, "rb")) == NULL) {
        for (int i = 0; i < SEATS; ++i) {
            plane[i] = (struct planestate) {
                    .seat_id=i + 1,
                    .status=EMPTY,
                    .last="",
                    .first=""
            };
        }
    } else {
        fread(plane, planestate_size, size, fp);
        fclose(fp);
    }
    while ((choice = choice_menu()) != 'f') {
        switch (choice) {
            case 'a':
                show_empty_seats_number(plane, SEATS);
                break;
            case 'b':
                show_empty_seats(plane, SEATS);
                break;
            case 'c':
                show_alphabetical_seats(plane, SEATS);
                break;
            case 'd':
                seat_id = get_opt_seat(1, SEATS);
                assignment(&plane[seat_id - 1]);
                break;
            case 'e':
                seat_id = get_opt_seat(1, SEATS);
                plane[seat_id - 1].status = EMPTY;
                plane[seat_id - 1].last[0] = '\0';
                plane[seat_id - 1].first[0] = '\0';
                break;
        }
    }
    //保存内存中的数据
    if ((fp = fopen(filepath, "wb")) != NULL) {
        fwrite(plane, planestate_size, size, fp);
        fclose(fp);
    } else {
        fputs("Save failed,Can't open file.\n", stderr);
        exit(EXIT_FAILURE);
    }

    return 0;
}

static char choice_menu() {
    const int st_size = 10;
    char st[st_size];
    //是否是a-e
    puts("To choose a function, enter its letter label:\n"
         "a) Show number of empty seats\n"
         "b) Show list of empty seats\n"
         "c) Show alphabetical list of seats\n"
         "d) Assign a customer to a seat assignment\n"
         "e) Delete a seat assignment\n"
         "f) Quit");
    char chs[] = "a|b|c|d|e|f";
    while (s_gets(st, st_size) == NULL || strchr(chs, st[0]) == NULL) {
        printf("输入a|b|c|d|e|f\n");
    }
    return st[0];
}

static void show_empty_seats_number(struct planestate plane[], int size) {
    printf("number of empty seats:");
    int sum = 0;
    for (int i = 0; i < size; ++i) {
        if (plane[i].status == EMPTY) {
            sum++;
        }
    }
    printf("%d\n", sum);
}

static void show_empty_seats(struct planestate plane[], int size) {
    printf("list of seats:");
    int sum = 0;
    for (int i = 0; i < size; ++i) {
        if (plane[i].status == EMPTY) {
            sum++;
            printf(" %d", plane[i].seat_id);
        }
    }
    if (sum == 0) {
        printf(" none\n");
        printf("full of seats");
    }
    puts("");
}

//Show alphabetical list of seats（根据姓名排序）
static void show_alphabetical_seats(struct planestate plane[], int size) {
    struct planestate p1[size];
    int sum = 0;
    for (int i = 0; i < size; ++i) {
        if (plane[i].status == TAKEN) {
            p1[sum] = plane[i];
            sum++;
        }
    }
    for (int i = 0; i < sum - 1; ++i) {
        for (int j = i + 1; j < sum; ++j) {
            if (strncmp(p1[i].first, p1[j].first, LEN) > 0) {
                struct planestate temp = p1[i];
                p1[i] = p1[j];
                p1[j] = temp;
            }
        }
    }
    if (sum==0){
        fputs("alphabetical list of seats:",stdout);
        puts("没有人预定座位.");
    } else{
        puts("alphabetical list of seats:");
    }
    for (int k = 0; k < sum; ++k) {c
        printf("%d:%s,%s\n", p1[k].seat_id, p1[k].first, p1[k].last);
    }
}

static void assignment(struct planestate *plan) {
    printf("Enter your full name:");
    while (scanf("%s%s", plan->first, plan->last)!=2) {
        fputs("Enter your full name(eg:孔明 诸葛):",stderr);
        eatline();
    }
    plan->status = TAKEN;
    eatline();
}

char *s_gets(char *st, int n) {
    char *ret_val;
    char *find;

    ret_val = fgets(st, n, stdin);
    if (ret_val) {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

static void eatline() {
    while (getchar() != '\n')
        continue;/* clear input line  */
}

static int get_i() {
    int i;
    int s = scanf("%d", &i);
    eatline();
    if (s != 1)return 0;
    return i;
}

static int get_opt_seat(int min, int max) {
    printf("输入你要操作的座位号(%d-%d):", min, max);
    int i;
    for (i = get_i(); i < min || i > max; i = get_i()) {
        printf("只能输入%d-%d:", min, max);
    }
    return i;
}

